package com.sheng.project.demo.utils;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.Security;

public class Sm4Util {

    // 加密算法、分组加密模式、分组填充方式
    // PKCS5Padding 以8个字节为一组进行分组加密
    // 定义分组加密模式使用：PKCS5Padding
    //    public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS7Padding";
    //    private static final String ENCODING = "utf-8";
    //
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
    //
    //    public static String decryptSm4(String hexKey, String cipherText) throws Exception {
    //        String decryptStr = "";
    //
    //        // hexString --> byte[]
    //        byte[] keyData = ByteUtils.fromHexString(hexKey);
    //        // hexString --> byte[]
    //        byte[] cipherData = ByteUtils.fromHexString(cipherText);
    //
    //        // 解密
    //        byte[] srcData = decryptSm4Padding(keyData, cipherData);
    //        decryptStr = new String(srcData, ENCODING);
    //        //        System.out.println(decryptStr);
    //        return decryptStr;
    //    }
    //
    //    private static byte[] decryptSm4Padding(byte[] key, byte[] cipherData) throws Exception {
    //        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);
    //        return cipher.doFinal(cipherData);
    //    }
    //
    //    private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception {
    //        Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
    //        Key sm4Key = new SecretKeySpec(key, algorithmName);
    //        cipher.init(mode, sm4Key);
    //        return cipher;
    //    }
    //
    //    public static String encryptSm4(String hexKey, String paramStr) throws Exception {
    //        String cipherText = "";
    //        byte[] keyData = ByteUtils.fromHexString(hexKey);
    //
    //        byte[] srcData = paramStr.getBytes(ENCODING);
    //
    //        byte[] cipherArray = encryptSm4Padding(keyData, srcData);
    //        // byte[] --> hexString
    //        cipherText = ByteUtils.toHexString(cipherArray);
    //        //        System.out.println(cipherText);
    //        return cipherText;
    //    }
    //
    //    private static byte[] encryptSm4Padding(byte[] keyData, byte[] srcData) throws Exception {
    //        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, keyData);
    //        return cipher.doFinal(srcData);
    //    }

    public static void main(String[] args) throws Exception {
//        System.out.println(UUID.randomUUID().toString().replace("-", ""));
//        String bytes = sm4Decrypt("0123456789abcdeffedcba9876543210",
//            "005a696249735ea94f0f5eda32a4887b0f893548ab76933d23687fd1a0656528");
//        System.out.println(bytes);
//        for (int i = 0; i < 20; i++) {
//            System.out.println(sm4Encrypt(UUID.randomUUID().toString().replace("-", ""), "测试加密数据112"));
//
//        }

        sm4Encrypt("12345678123456781234567812345672", "aaaa");
    }

    public static String sm4Encrypt(String hexKey, String plainText) {
        String algo = "SM4/ECB/PKCS7Padding";
        byte[] keyBytes = Hex.decode(hexKey);
        byte[] plain = plainText.getBytes();
        if (keyBytes.length != 16)
            throw new RuntimeException("err key length");

        try {
            Key key = new SecretKeySpec(keyBytes, "SM4");
            Cipher out = Cipher.getInstance(algo, "BC");
            out.init(Cipher.ENCRYPT_MODE, key);
            return Hex.toHexString(out.doFinal(plain));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String sm4Decrypt(String hexKey, String hexCipher) {
        String algo = "SM4/ECB/PKCS7Padding";
        byte[] keyBytes = Hex.decode(hexKey);
        byte[] cipher = Hex.decode(hexCipher);
        if (keyBytes.length != 16)
            throw new RuntimeException("err key length");
        if (cipher.length % 16 != 0)
            throw new RuntimeException("err data length");

        try {
            Key key = new SecretKeySpec(keyBytes, "SM4");
            Cipher in = Cipher.getInstance(algo, "BC");
            in.init(Cipher.DECRYPT_MODE, key);
            return new String(in.doFinal(cipher));

        } catch (Exception e) {
            throw new RuntimeException(e);
            //            return null;
        }

    }

}
